package com.fruits.login.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fruits.login.dao.HallUrlDAO;
import com.fruits.login.dao.LoginRecodeDao;
import com.fruits.login.dao.PlayerInfoDAO;
import com.fruits.login.model.HallUrl;
import com.fruits.login.model.PlayerLoginInfo;
import com.fruits.login.model.ReturnMsg;
import com.fruits.login.model.properties.LoginProperties;
import com.fruits.login.service.CodeService;
import com.fruits.login.service.LoginService;
import com.sghd.common.utils.codec.CryptUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
//import sun.misc.BASE64Encoder;

import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Base64;
import java.util.List;
import java.util.Random;

@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Value("${ios.isAudit}")
    private int isAudit;
    @Value("${ios.auditPhone}")
    private String auditPhone;
    @Value("${ios.auditCode}")
    private String auditCode;
    @Autowired
    private CodeService codeService;

    @Autowired
    private PlayerInfoDAO playerInfoDAO;

    @Autowired
    private HallUrlDAO hallUrlDAO;

    @Autowired
    private LoginRecodeDao loginRecodeDao;

    @Override
    public ReturnMsg loginByPhoneAndCode(PlayerLoginInfo playerLoginInfo) {
        ReturnMsg msg = codeService.checkCode(playerLoginInfo.getPhone(), playerLoginInfo.getCode());

        if (isAudit == 1) {
            if (playerLoginInfo.getPhone().equals(auditPhone) && playerLoginInfo.getCode().equals(auditCode)) {
                msg.setState(LoginProperties.RETURN_MSG_SUCCESS);
            }
        }

        if (msg.getState() != LoginProperties.RETURN_MSG_SUCCESS) {
            return msg;
        }

        synchronized (playerLoginInfo) {
            //从数据库中获取对应账号
            List<PlayerLoginInfo> playerInfoByDB = playerInfoDAO.isHavePlayerByPhone(playerLoginInfo.getPhone());
            //数据库中没有对应玩家,需要生成新玩家
            if (playerInfoByDB == null || playerInfoByDB.size() == 0) {
                if (playerLoginInfo.getDeviceMac() == null) {
                    msg.setState(0);
                    msg.setInfo("缺少mac参数");
                    logger.info("缺少mac参数");
                    return msg;
                }
                List<PlayerLoginInfo> playerInfoByMac = playerInfoDAO.findPlayerInfoByMac(playerLoginInfo.getDeviceMac());
                if (playerInfoByMac.size() > 0) {
                    playerLoginInfo.setType(0);
                    playerInfoDAO.updatePlayerInfoBy(playerLoginInfo);
                    playerLoginInfo.setUid(playerInfoByMac.get(0).getUid());
                    logger.info(playerLoginInfo.getPhone() + "登录绑定手机号" + playerLoginInfo.getDeviceMac());
                } else {
                    if (!createPlayer(playerLoginInfo)){
                        return retuenPlayerInfoWhereFaile("注册失败");
                    }
                    logger.info(playerLoginInfo.getPhone() + "登录绑定手机号;新生成");
                }
            } else {
                playerLoginInfo = playerInfoByDB.get(0);
            }
            //返回玩家信息
            return retuenPlayerInfoWhereSuccess(playerLoginInfo);
        }
    }

    @Override
    public ReturnMsg loginByUid(PlayerLoginInfo playerLoginInfo) {
        synchronized (playerLoginInfo) {
            ReturnMsg msg = new ReturnMsg();
            //1.查找数据库是否有对应的uid记录
            List<PlayerLoginInfo> playerLoginInfos = playerInfoDAO.findPlayerInfoByUid(playerLoginInfo.getUid());
            //有,返回第一条
            if (playerLoginInfos.size() > 0) {
                playerLoginInfo = playerLoginInfos.get(0);
                return retuenPlayerInfoWhereSuccess(playerLoginInfo);
            }
            logger.info("没有查找到对应的" + playerLoginInfo.getUid() + "信息");
            return loginByMac(playerLoginInfo);
        }
    }

    @Override
    public ReturnMsg loginByMac(PlayerLoginInfo playerLoginInfo) {
        synchronized (playerLoginInfo) {
            //查找数据库中是否有对应deviceMac记录
            List<PlayerLoginInfo> playerLoginInfos = playerInfoDAO.findPlayerInfoByMac(playerLoginInfo.getDeviceMac());
            //有,取出返回
            if (playerLoginInfos.size() > 0) {
                logger.info("返回deviceMac:" + playerLoginInfo.getDeviceMac() + " 玩家信息");
                return retuenPlayerInfoWhereSuccess(playerLoginInfos.get(0));
            }
            //没有,则生成一个游客账号
            if (!createPlayer(playerLoginInfo)){
                return retuenPlayerInfoWhereFaile("注册失败");
            }
            //并返回该玩家信息
            return retuenPlayerInfoWhereSuccess(playerLoginInfo);
        }
    }

    /**
     * 生成uid:CREATE_UID_KEY+deviceMac+时间戳+次数
     *
     * @return
     */
    private String createUid(List<String> uids, String deviceMac, int i) {
        String uid = CryptUtils.generateToken(LoginProperties.CREATE_UID_KEY, deviceMac, System.currentTimeMillis());
        if (uids.contains(uid)) {
            return createUid(uids, deviceMac, i++);
        }
        return uid;
    }

    /**
     * 第一次进入生成uid
     *
     * @param playerLoginInfo
     * @return
     */
    private String createUid(PlayerLoginInfo playerLoginInfo) {
        List<String> uids = playerInfoDAO.findUidAll();
        return createUid(uids, playerLoginInfo.getDeviceMac(), 0);
    }

    /**
     * 获取一个开启的大厅信息
     *
     * @return
     */
    private HallUrl getOneHallInfo() {
        Random random = new Random();
        List<HallUrl> hallUrls = hallUrlDAO.findAllHallUrl();
        return hallUrls.get(random.nextInt(hallUrls.size()));
    }

    /**
     * 登录成功时返回玩家信息
     *
     * @param playerLoginInfo
     * @return
     */
    private ReturnMsg retuenPlayerInfoWhereSuccess(PlayerLoginInfo playerLoginInfo) {
        ReturnMsg msg = new ReturnMsg();
        msg.setState(1);
        JSONObject playerInfo = new JSONObject();
        //playerInfo.put("playerId", playerLoginInfo.getPlayerId());
        playerInfo.put("uid", playerLoginInfo.getUid());
        HallUrl url = getOneHallInfo();
        playerInfo.put("hallUrl", url);
        //玩家类型:t游客f手机
        boolean type = true;
        if (playerLoginInfo.getPhone() != null) {
            type = false;
        }
        playerInfo.put("type", type);
        long timestamp = System.currentTimeMillis() / 1000;
        playerInfo.put("timestamp", timestamp);
        playerInfo.put("token", CryptUtils.generateToken(LoginProperties.CREATE_TOKEN_KEY, playerLoginInfo.getUid(), timestamp, type,url.getId()));
        msg.addJSONObject(playerInfo);
        System.out.println("登录成功消息");
        msg.getResult().forEach(json -> System.out.print(json.toString()));
        System.out.println();
        /*添加登录记录*/
        loginRecodeDao.save(playerLoginInfo.getUid());
        return msg;
    }

    /**
     * 登录失败时返回错误提示
     *
     * @param errorMessage
     * @return
     */
    @Override
    public ReturnMsg retuenPlayerInfoWhereFaile(String errorMessage) {
        ReturnMsg msg = new ReturnMsg();
        msg.setState(0);
        msg.setInfo(errorMessage);
        return msg;
    }

    @Override
    public boolean signValidator(@Valid PlayerLoginInfo info) {
        String s = info.getTimestamp() + info.getDeviceMac() + info.getType() + LoginProperties.CREATE_SIGN_KEY;
        Base64.Encoder encoder = Base64.getEncoder();
        try {
            byte[] textByte = s.getBytes("UTF-8");
            String sign = encoder.encodeToString(textByte);
            logger.info("签名:" + sign);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 创建新玩家
     */
    private boolean createPlayer(PlayerLoginInfo info){
        info.setUid(createUid(info));
        info.setType(0);
        if (info.getPhone()==null){
            info.setType(1);
        }
        try{
            info.setTimestamp(new Date());
//            playerLoginInfo.setCreateTime(new Date());
            if (info.getPhone()==null){
//                uid,deviceMac,createTime,type
                playerInfoDAO.createPlayerNotPhone(info);
//                playerInfoDAO.createPlayerNotPhone(info.getUid(),info.getDeviceMac(),new Date(),info.getType());
            }else {
//                playerInfoDAO.createPlayerHavePhone(info.getPhone(),info.getUid(),info.getDeviceMac(),new Date(),info.getType());
                playerInfoDAO.createPlayerHavePhone(info);
            }
            logger.info("注册成功");
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

//    public static void main(String[] args) {
//        PlayerLoginInfo loginInfo = new PlayerLoginInfo();
//        loginInfo.setDeviceMac("13524asdf;kahft");
//        loginInfo.setTimestamp(new Date().getTime() + "");
//        loginInfo.setType(0);
//        LoginService service = new LoginServiceImpl();
//        service.signValidator(loginInfo);
//    }

    /*public static void main(String[] args) throws UnsupportedEncodingException {
        *//*long mills = 1548742369656L;
        String tokenStr = CryptUtils.generateToken(LoginProperties.CREATE_TOKEN_KEY,"123", "abc");
        System.out.println(tokenStr);*//*
        String abc = "aaaaa";
        String key = "abcd1234";
        String en = CryptUtils.encryptDES(abc, key);
        System.out.println(en);
        //4E27CE07DB8A68B9

        String de = CryptUtils.decryptDES("DFD25EBAED538EAF", key);
        System.out.println(de);
        //a3bb321d5ea3112af5f459aef3f56eed
    }*/
}
